/*
    a09_application -
    
    演示GApplication的基本用法.

    命令,
        $./main.exe <sub> <para>
    sub,
        cmd, 
            echo
        action,
            list
            action1
            action2
        open,
            filename

    GApplication对arg的默认处理参见g_application_real_local_command_line()
*/
#include <glib.h>
#include <gio/gio.h>

static void
new_activated (GSimpleAction *action,
               GVariant      *parameter,
               gpointer       user_data)
{
    GApplication *app = user_data;
    g_application_activate (app);
}

static void
quit_activated (GSimpleAction *action,
                GVariant      *parameter,
                gpointer       user_data)
{
    GApplication *app = user_data;
    g_application_quit (app);
}

static void
action1_activated (GSimpleAction *action,
                   GVariant      *parameter,
                   gpointer       user_data)
{
    g_print ("activate action1\n");
}

static void
action2_activated (GSimpleAction *action,
                   GVariant      *parameter,
                   gpointer       user_data)
{
    GVariant *state;

    state = g_action_get_state (G_ACTION (action));
    g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
    g_print ("activate action2 %d\n", !g_variant_get_boolean (state));
    g_variant_unref (state);
}

static void
change_action2 (GSimpleAction *action,
                GVariant      *state,
                gpointer       user_data)
{
    g_print ("change action2 %d\n", g_variant_get_boolean (state));
}

static void do_startup(GApplication *app)
{
    static GActionEntry actions[] = {
        { "new", new_activated, NULL, NULL, NULL },
        { "quit", quit_activated, NULL, NULL, NULL },
        { "action1", action1_activated, NULL, NULL, NULL },
        { "action2", action2_activated, "b", "false", change_action2 }
    };

    g_print("do_startup\n");
    g_action_map_add_action_entries (G_ACTION_MAP (app),
                                    actions, G_N_ELEMENTS (actions),
                                    app);

}

static void do_activate(GApplication *app)
{
    g_application_hold (app);
    g_print ("activated\n");
    g_application_release (app);
}

static void do_open(GApplication *app,
               GFile      **files,
               gint          n_files,
               gchar        *hint,
               gpointer      user_data)
{
    gint i;

    g_print("do_open\n");

    g_application_hold (app);

    g_print ("open");
    for (i = 0; i < n_files; i++)
    {
        gchar *uri = g_file_get_uri (files[i]);
        g_print (" %s", uri);
        g_free (uri);
    }
    g_print ("\n");

    g_application_release (app);
}


static int do_command_line(GApplication *app, GApplicationCommandLine *cmdline)
{
    gchar** argv;
    gint argc;
    gint i;

    
    g_application_hold(app);

    argv = g_application_command_line_get_arguments(cmdline, &argc);
    g_print("do_command_line %s\n", argv[1]);

    if(argc > 1)
    {
        if(g_strcmp0(argv[1], "echo") == 0)
        {
            g_print("cmdline");
            for(i = 0; i< argc; i++)
            {
                g_print(" %s", argv[i]);
            }
            g_print("\n");
        }
        else
        {
            g_print("unknow the cmd: %s\n", argv[1]);
        }
    }

    g_strfreev(argv);

    g_application_release(app);

    return 0;       // the exit status of the calling process.
}

gboolean do_idle(gpointer data)
{
    gchar** argv = data;
    GApplication *app;
    gchar** actions;
    gint i;

    g_print("do_idle\n");
    if(g_strcmp0(argv[1], "action") == 0)
    {
        app = g_application_get_default();
        if(g_strcmp0(argv[2], "list") == 0)
        {
            g_message("list actions:");
            actions = g_action_group_list_actions(G_ACTION_GROUP(app));
            for(int i = 0; actions[i]; i++)
            {
                g_message("    %s", actions[i]);
            }

            g_strfreev(actions);
        }
        else if(g_strcmp0(argv[2], "action1")==0)
        {
            g_action_group_activate_action(G_ACTION_GROUP(app), "action1", NULL);
        }
        else if(g_strcmp0(argv[2], "action2")==0)
        {
          g_action_group_change_action_state (G_ACTION_GROUP (app),
                                              "action2",
                                              g_variant_new_boolean (TRUE));
        }
        else
        {
            g_message("do default act");
        }
        g_application_release(app);
    }

    return G_SOURCE_REMOVE;
}

int main(int argc, char* argv[])
{
    GApplication *app;
    int ret;
    int app_flags = G_APPLICATION_FLAGS_NONE;
    //app_flags |= G_APPLICATION_SEND_ENVIRONMENT;        //使用env
    if(g_strcmp0(argv[1], "open") == 0)
    {
        app_flags |= G_APPLICATION_HANDLES_OPEN;
    }
    else if(g_strcmp0(argv[1], "cmd") == 0)
    {
        app_flags |= G_APPLICATION_HANDLES_COMMAND_LINE;
    }
    else if(g_strcmp0(argv[1], "action") == 0)      //留待idle中处理.
    {
        app_flags |= G_APPLICATION_HANDLES_COMMAND_LINE;
    }
    else
    {
        // app_flags |= G_APPLICATION_HANDLES_OPEN;
    }

    g_print("app_flags= 0x%x\n", app_flags);

    app = g_application_new(NULL, app_flags);

    g_signal_connect(app, "startup", G_CALLBACK(do_startup), NULL);
    g_signal_connect(app, "activate", G_CALLBACK(do_activate), NULL);
    g_signal_connect(app, "open", G_CALLBACK(do_open), NULL);
    g_signal_connect(app, "command-line", G_CALLBACK(do_command_line), NULL);

    guint timeout;
    timeout = g_application_get_inactivity_timeout(app);
    g_print("app timeout=%d\n", timeout);

    //g_application_set_inactivity_timeout(app, 10000);

    if(g_strcmp0(argv[1], "action") == 0)
    {
        g_application_set_inactivity_timeout(app, 0);
        g_application_hold(app);
        g_idle_add(do_idle, argv);
    }

    ret = g_application_run(app, argc-1, argv+1);   //skip the first arg

    g_object_unref(app);

    g_print("exist status %d\n", ret);
    return 0;
}